Managed runtimes provide methods that enable managed code to interface with unmanaged machine code (e.g., native code). Typical managed runtimes maintain a state for each thread, such as a “running” state and a “native” state. In the “running” state, a thread is actively manipulating managed data in the heap, and periodically the thread checks for suspend requests that enable a garbage collector to reclaim unused memory. Conversely, in the “native” state, a thread does not check for a suspend request.
In typical managed runtimes, the state of a thread is changed when the thread is transitioning from executing managed code to executing native code. Likewise, the state of the thread is changed when the thread is transitioning from executing native code to executing managed code. The change in the state of the thread is performed under a lock and is relatively time consuming. For code segments that pertain to a user interface, key methods are often implemented in native code and invoked from managed code. Accordingly, the locking overhead associated with transitioning from managed code to native code can cause a lag in the responsiveness of the user interface.